package com.Astart 
{
	import com.Astart.astartInterface.Igrid;
	import com.Astart.astartInterface.Inode;
	import flash.display.BitmapData;
	import flash.display.Graphics;
	import flash.display.Shape;
	import flash.geom.Matrix;
	import flash.geom.Rectangle;
	/**
	 * ...
	 * @author weoweo
	 */
	public class Grid implements Igrid
	{
		private var _nodes:Array;
		private var _width:Number;
		private var _height:Number;
		private var _row:int;
		private var _col:int;
		
		private var _gridRefresh:Boolean;
		
		public function Grid(w:Number,h:Number,r:int=30,c:int=30) 
		{
			this._width = w;
			this._height = h;
			this._row = r;
			this._col = c;
			_gridRefresh = false;
			init();
			
		}
		private function init():void {
			this.nodePool = [];
			this._nodes = [];
		}
		
		public function setSize(w:Number,h:Number):void {
			this._width = w;
			this._height = h;
			_gridRefresh = false;
		}
		public function setRCnum(r:int,c:int):void {
			
			this._row = r; this._col = c;
			_gridRefresh = false;
		}
		
		
		public function drawGrid(g:Graphics):void {
			updata();
			g.clear();
			g.lineStyle(1, 0x999900, 0.6);
		
			var startX:Number = 0;
			while (startX < _width) {
				g.moveTo(startX, 0);
				g.lineTo(startX, this._height);
				startX += _nodeWidth;
			}
			g.moveTo(startX, 0);
			g.lineTo(startX, this._height);
			
			
			var startY:Number = 0;
			while (startY < this._height) {
				g.moveTo(0, startY);
				g.lineTo(this._width, startY);
				startY += _nodeHeight;
			}
			g.moveTo(0, startY);
			g.lineTo(this._width, startY);
		}
		private var _canvas:BitmapData;
		public function canvasGrid(canvas:BitmapData):void {
			if (canvas == null) return; 
			canvas.fillRect(canvas.rect, 0xFFFFFFF);
			var gridShape:Shape = new Shape();
			drawGrid(gridShape.graphics);
			canvas.draw(gridShape, null, null, null, null, false);
			gridShape = null;
			_canvas = canvas;
		}
		
		
		
		
		public function updata():void {
			
			if (_gridRefresh) return;
			_gridRefresh = true;
			
			for each(var arr:Array in _nodes) {
				nodePool.concat(arr);
			}
			
			_nodes = null;
			_nodes = [];
			
			_nodeWidth = this._width / this._row;
			_nodeHeight = this._height / this._col;
			trace("nodeWidth " + _nodeWidth + "  _nodeHeight " + _nodeHeight);
			
			for (var i:int = 0; i < this._col ; i++ ) {
				
				_nodes[i] = [];
				for (var s:int = 0; s < this._row; s++ ) {
					var node:Node = getNodeFormPool();
					node.reset();
					node.x = s;
					node.y = i;
					_nodes[i][s] = node;
				}
			}
		}
		private var _nodeWidth:Number;
		private var _nodeHeight:Number;
		
		public function get nodeWidth():Number {
			return _nodeWidth;
		}
		public function get nodeHeight():Number {
			return _nodeHeight
		}
		
		
		
		
		private var nodePool:Array;
		private function getNodeFormPool():Node {
			return nodePool.shift() || new Node();
		}
		
		
		private var _startShape:Shape;
		private var _endShape:Shape;
		
		
		private var _startNode:Node;
		public function set startNode(n:Inode):void {
			_startNode = n as Node;
			if (_startNode == null) return;
			if (_startShape == null) {
				_startShape = new Shape();
				_startShape.graphics.beginFill(0xFF0000, 1);
				var size:Number = nodeWidth / 3;
				var pos:Number = (nodeWidth ) / 2;
				_startShape.graphics.drawCircle(pos, pos, size);
				_startShape.graphics.endFill();
			}
			if (_canvas) {
				var xpos:Number = _startNode.x * nodeWidth; var ypos:Number = _startNode.y * nodeHeight;
				_canvas.draw(_startShape, new Matrix(1, 0, 0, 1,xpos,ypos ), null, null, null, false);
			}
		}
		public function get startNode():Inode {
			return this._startNode as Inode;
		}
		
		private var _endNode:Node;
		public function set endNode(n:Inode):void {
			if (_endNode != n) this._endNode = n as Node;
			if (_endNode == null) return;
			if (_endShape == null) {
				_endShape = new Shape();
				_endShape.graphics.beginFill(0x00FF00, 1);
				var size:Number = nodeWidth / 3;
				var pos:Number = (nodeWidth ) / 2;
				_endShape.graphics.drawCircle(pos, pos, size);
				_endShape.graphics.endFill();
			}
			if (_canvas) {
				var xpos:Number = _endNode.x * nodeWidth; var ypos:Number = _endNode.y * nodeHeight;
				_canvas.draw(_endShape, new Matrix(1, 0, 0, 1,xpos,ypos ), null, null, null, false);
			}
		}
		
		
		public function get endNode():Inode {
			return this._endNode as Inode;
		}
		
		
		
		public function drawRectByArr(v:Array,color:uint):void {
			
			if (_canvas) {
				
				for each(var n:Node in v) {
				
					var x:Number = n.x * nodeWidth; var y:Number = n.y * nodeHeight;
					var rect:Rectangle = new Rectangle(x+1, y+1, _nodeWidth-2, _nodeHeight-2);
					_canvas.fillRect(rect,color);
				}
			}
		}
		public function drawPathLine(g:Graphics, arr:Array,cl:uint):void {
			
			g.lineStyle(0.1, cl);
			g.moveTo((arr[0].x+0.5) * _nodeWidth, (arr[0].y+0.5) * _nodeHeight);
			var cn:Node;
			for (var i:int = 1; i < arr.length; i++ ) {
				cn = arr[i] as Node;
				g.lineTo((cn.x+0.5) * _nodeWidth, (cn.y+0.5)* _nodeHeight);
			}
		}
		
		
		public function drawUnWalks():void {
			var arr:Array = [];
			for each(var a:Array in _nodes) {
				for each(var n:Node in a) {
					if (!n.walkAble) arr.push(n);
				}
			}
			
			var color:uint = 0x000000;
			drawRectByArr(arr, color);
		}
		
		public function changeNodeStaByXY(x:Number,y:Number,status:int=-1 ):void {
			var node:Node = getNodeByXY(x, y);
			if (node == null) return;
			
			var nodeSta:Boolean = !node.walkAble;
			if (status == 1) nodeSta = true;
			else if (status == 0) nodeSta = false;
			node.walkAble = nodeSta;
		}
		
		public function getNodeByXY(x:Number, y:Number ):Node {
			
			if (x<0||y<0||x > _width || y > _height) {
				
				//throw new Error("获取节点失败，超出定义的范围."+" x: "+x+"  y: "+y);
				return null;
			}
			
			var col:int = int(y / _nodeHeight);
			var row:int = int(x / _nodeWidth);
			
			if (_nodes[col] == null || _nodes[col][row] == null) {
				return null;
				throw new Error("获取节点失败，无此节点."+col+" "+row+"  x: "+x+"  y:"+y);
			}
			return _nodes[col][row] as Node;
		}
		
		public function get nodes():Array {
			return _nodes;
		}
		
		
		
		public function get row():int {
			return this._row;
		}
		public function get col():int {
			return this._col;
		}
		
		public function get width():Number {
			return this._width;
		}
		public function get height():Number {
			return this._height;
		}
		
		public function get numRows():int {
			return this._row;
		}
		public function get numCols():int {
			return this._col;
		}
		public function nodesRest():void {
			
			for each(var a:Array in _nodes) {
				for each(var n:Node in a) {
					if (n.visited) n.visited = false;
				}
			}
		}
		
		
		
		
	}

}